#pragma once

#include <string>
#include <memory>
#include <vector>
#include <mutex>
#include <fstream>
#include <sstream>
#include <chrono>
#include <iomanip>
#include <functional>
#include <thread>
#include <queue>
#include <condition_variable>
#include <atomic>

namespace yquote {

// 日志级别枚举
enum class LogLevel : int {
    TRACE = 0,
    DEBUG = 1,
    INFO = 2,
    WARN = 3,
    ERROR = 4,
    FATAL = 5
};

// 日志消息结构
struct LogMessage {
    LogLevel level;
    std::string message;
    std::string file;
    int line;
    std::string function;
    std::chrono::system_clock::time_point timestamp;
    std::thread::id thread_id;
    
    LogMessage(LogLevel lvl, const std::string& msg, const std::string& f, 
               int l, const std::string& func)
        : level(lvl), message(msg), file(f), line(l), function(func),
          timestamp(std::chrono::system_clock::now()),
          thread_id(std::this_thread::get_id()) {}
};

// 日志输出接口
class LogSink {
public:
    virtual ~LogSink() = default;
    virtual void write(const LogMessage& msg) = 0;
    virtual void flush() {}
};

// 控制台输出
class ConsoleSink : public LogSink {
public:
    ConsoleSink(bool use_colors = true);
    void write(const LogMessage& msg) override;
    void flush() override;

private:
    bool use_colors_;
    std::mutex mutex_;
    std::string getColorCode(LogLevel level) const;
    std::string getResetCode() const;
    std::string getLevelString(LogLevel level) const;
};

// 文件输出
class FileSink : public LogSink {
public:
    FileSink(const std::string& filename, bool append = true);
    ~FileSink();
    void write(const LogMessage& msg) override;
    void flush() override;

private:
    std::ofstream file_;
    std::mutex mutex_;
    std::string getLevelString(LogLevel level) const;
};

// 滚动文件输出
class RotatingFileSink : public LogSink {
public:
    RotatingFileSink(const std::string& base_filename, size_t max_size, size_t max_files);
    ~RotatingFileSink();
    void write(const LogMessage& msg) override;
    void flush() override;

private:
    std::string base_filename_;
    size_t max_size_;
    size_t max_files_;
    size_t current_size_;
    std::ofstream file_;
    std::mutex mutex_;
    
    void rotateFile();
    std::string getCurrentFilename() const;
    std::string getLevelString(LogLevel level) const;
};

// 自定义输出（回调函数）
class CallbackSink : public LogSink {
public:
    using Callback = std::function<void(const LogMessage&)>;
    
    CallbackSink(Callback callback);
    void write(const LogMessage& msg) override;

private:
    Callback callback_;
    std::mutex mutex_;
};

// 日志格式化器
class LogFormatter {
public:
    virtual ~LogFormatter() = default;
    virtual std::string format(const LogMessage& msg) = 0;
};

// 默认格式化器
class DefaultFormatter : public LogFormatter {
public:
    DefaultFormatter(const std::string& pattern = "[%Y-%m-%d %H:%M:%S.%f] [%l] [%t] %v (%s:%#)");
    std::string format(const LogMessage& msg) override;

private:
    std::string pattern_;
    std::string formatTimestamp(const std::chrono::system_clock::time_point& tp) const;
    std::string getLevelString(LogLevel level) const;
    std::string getThreadIdString(std::thread::id id) const;
};

// 异步日志器
class AsyncLogger {
public:
    AsyncLogger();
    ~AsyncLogger();
    
    void start();
    void stop();
    void enqueue(LogMessage&& msg);

private:
    std::queue<LogMessage> queue_;
    std::mutex queue_mutex_;
    std::condition_variable condition_;
    std::atomic<bool> running_;
    std::thread worker_thread_;
    
    void workerLoop();
};

// 主日志器类
class Logger {
public:
    static Logger& getInstance();
    
    // 设置日志级别
    void setLevel(LogLevel level);
    LogLevel getLevel() const;
    
    // 添加输出目标
    void addSink(std::shared_ptr<LogSink> sink);
    void removeSink(std::shared_ptr<LogSink> sink);
    void clearSinks();
    
    // 设置格式化器
    void setFormatter(std::shared_ptr<LogFormatter> formatter);
    
    // 启用/禁用异步模式
    void setAsync(bool async);
    
    // 日志输出方法
    void log(LogLevel level, const std::string& message, 
             const std::string& file, int line, const std::string& function);
    
    template<typename... Args>
    void log(LogLevel level, const std::string& file, int line, 
             const std::string& function, const std::string& format, Args&&... args);
    
    // 便捷方法
    void trace(const std::string& message, const std::string& file, int line, const std::string& function);
    void debug(const std::string& message, const std::string& file, int line, const std::string& function);
    void info(const std::string& message, const std::string& file, int line, const std::string& function);
    void warn(const std::string& message, const std::string& file, int line, const std::string& function);
    void error(const std::string& message, const std::string& file, int line, const std::string& function);
    void fatal(const std::string& message, const std::string& file, int line, const std::string& function);
    
    template<typename... Args>
    void trace(const std::string& file, int line, const std::string& function, 
               const std::string& format, Args&&... args);
    template<typename... Args>
    void debug(const std::string& file, int line, const std::string& function, 
               const std::string& format, Args&&... args);
    template<typename... Args>
    void info(const std::string& file, int line, const std::string& function, 
              const std::string& format, Args&&... args);
    template<typename... Args>
    void warn(const std::string& file, int line, const std::string& function, 
              const std::string& format, Args&&... args);
    template<typename... Args>
    void error(const std::string& file, int line, const std::string& function, 
               const std::string& format, Args&&... args);
    template<typename... Args>
    void fatal(const std::string& file, int line, const std::string& function, 
               const std::string& format, Args&&... args);
    
    // 刷新所有输出
    void flush();

private:
    Logger() = default;
    ~Logger();
    
    LogLevel level_;
    std::vector<std::shared_ptr<LogSink>> sinks_;
    std::shared_ptr<LogFormatter> formatter_;
    std::unique_ptr<AsyncLogger> async_logger_;
    bool async_mode_;
    mutable std::mutex mutex_;
    
    void writeToSinks(const LogMessage& msg);
    std::string formatMessage(const std::string& format, ...) const;
};

// 便捷宏定义
#define LOG_TRACE(msg) yquote::Logger::getInstance().trace(msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_DEBUG(msg) yquote::Logger::getInstance().debug(msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_INFO(msg) yquote::Logger::getInstance().info(msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_WARN(msg) yquote::Logger::getInstance().warn(msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_ERROR(msg) yquote::Logger::getInstance().error(msg, __FILE__, __LINE__, __FUNCTION__)
#define LOG_FATAL(msg) yquote::Logger::getInstance().fatal(msg, __FILE__, __LINE__, __FUNCTION__)

// 格式化日志宏
#define LOG_TRACE_FMT(fmt, ...) yquote::Logger::getInstance().trace(__FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_DEBUG_FMT(fmt, ...) yquote::Logger::getInstance().debug(__FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_INFO_FMT(fmt, ...) yquote::Logger::getInstance().info(__FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_WARN_FMT(fmt, ...) yquote::Logger::getInstance().warn(__FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_ERROR_FMT(fmt, ...) yquote::Logger::getInstance().error(__FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)
#define LOG_FATAL_FMT(fmt, ...) yquote::Logger::getInstance().fatal(__FILE__, __LINE__, __FUNCTION__, fmt, ##__VA_ARGS__)

// 模板方法实现
template<typename... Args>
void Logger::log(LogLevel level, const std::string& file, int line, 
                 const std::string& function, const std::string& format, Args&&... args) {
    if (level < level_) return;
    
    std::ostringstream oss;
    ((oss << args), ...);
    std::string message = formatMessage(format, std::forward<Args>(args)...);
    
    log(level, message, file, line, function);
}

template<typename... Args>
void Logger::trace(const std::string& file, int line, const std::string& function, 
                   const std::string& format, Args&&... args) {
    log(LogLevel::TRACE, file, line, function, format, std::forward<Args>(args)...);
}

template<typename... Args>
void Logger::debug(const std::string& file, int line, const std::string& function, 
                   const std::string& format, Args&&... args) {
    log(LogLevel::DEBUG, file, line, function, format, std::forward<Args>(args)...);
}

template<typename... Args>
void Logger::info(const std::string& file, int line, const std::string& function, 
                  const std::string& format, Args&&... args) {
    log(LogLevel::INFO, file, line, function, format, std::forward<Args>(args)...);
}

template<typename... Args>
void Logger::warn(const std::string& file, int line, const std::string& function, 
                  const std::string& format, Args&&... args) {
    log(LogLevel::WARN, file, line, function, format, std::forward<Args>(args)...);
}

template<typename... Args>
void Logger::error(const std::string& file, int line, const std::string& function, 
                   const std::string& format, Args&&... args) {
    log(LogLevel::ERROR, file, line, function, format, std::forward<Args>(args)...);
}

template<typename... Args>
void Logger::fatal(const std::string& file, int line, const std::string& function, 
                   const std::string& format, Args&&... args) {
    log(LogLevel::FATAL, file, line, function, format, std::forward<Args>(args)...);
}

} // namespace yquote 